﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Timers;
using XYAC.Framework.MonitorTireMaterialManual.Context;
using XYAC.Framework.MonitorTireMaterialManual.Entities;
using XYAC.Framework.MonitorTireMaterialManual.Extensions;
using XYAC.Framework.MonitorTireMaterialManual.IServices;

namespace XYAC.Framework.MonitorTireMaterialManual.ViewModels
{
    /// <summary>
    /// 主窗体视图模型,此类主要用户控制定时task执行
    /// </summary>
    public partial class MainWindowViewModel : ViewModelBase
    {


        #region Const 
        private const String __TABLE_DwlData = "DwlData";
        private const String __TABLE_LaserData = "LaserData";
        private const String __TABLE_SpecVal = "SpecVal";
        private const string __REMOTE_SYNC_STATE_PENDING = "PENDING";
        private const string __REMOTE_SYNC_STATE_COMPLETE = "COMPLETE";
        private const string __REMOTE_SYNC_STATE_PLANED = "PLANED";
        #endregion



        public MainWindowViewModel(IOptionsMonitor<AppConfig> appConfig, ILogger<MainWindowViewModel> logger, IServiceProvider provider)
        {
            this.AppConfig = appConfig;
            this.Logger = logger;
            this.provider = provider;
            //初始化定时器任务
            InitializeTasks();
        }
        #region Attributes
        private IServiceProvider provider;

        public System.Timers.Timer ProduceDataUploaderTimer { get; private set; }
        //public System.Timers.Timer InspectTimer { get; private set; }
        public System.Timers.Timer DataCleanerTimer { get; private set; }
        //public System.Timers.Timer SyncSpecInfoTimer { get; private set; }
        /// <summary>
        /// 机台类型
        /// </summary> 
        public System.Timers.Timer FailedDataUploaderTimer { get; private set; }
        public IOptionsMonitor<AppConfig> AppConfig { get; }
        public ILogger Logger { get; }
        public System.Timers.Timer HisDataSyncToLocalTimer { get; private set; }
        private CancellationTokenSource HisDataSyncCancelToken { get; set; }
        public System.Timers.Timer HisDataLocaSyncToMesTimer { get; private set; }
        public IEnumerable<(string Name, String Subtitle)> TabItemHeaders = new List<(string Name, String Subtitle)>()
        {
                new  ("质量数据上传历史",""),
                new ("系统设置","")
        };
        #endregion


        /// <summary>
        /// 初始化定时任务
        /// </summary>
        private void InitializeTasks()
        {
            try
            {
                //数据库检查工具,用于创建次日的数据库
                //DbCheckerTimer_Elapsed(null, null);
                DbCheckerTimer = new System.Timers.Timer();
                DbCheckerTimer.Elapsed += DbCheckerTimer_Elapsed;
                DbCheckerTimer.Interval = 1 * 60 * 60 * 1000;//一小时
                DbCheckerTimer.Start();

                //定期数据清理
                //DataCleanerTimer_Elapsed(null, null);
                DataCleanerTimer = new System.Timers.Timer();
                DataCleanerTimer.Elapsed += DataCleanerTimer_Elapsed;
                DataCleanerTimer.Interval = 1 * 60 * 60 * 1000;//1小时
                DataCleanerTimer.Start();

                //上传数据到MES中间表
                ProduceDataUploaderTimer = new System.Timers.Timer();
                ProduceDataUploaderTimer.Elapsed += ProduceDataUploaderTimer_Elapsed;
                ProduceDataUploaderTimer.Interval = 30 * 1000;//30秒
                ProduceDataUploaderTimer.Start();

                //DownloadInspectData();
                //下载中间表数据
                InspectTimer = new System.Timers.Timer();
                InspectTimer.Elapsed += InspectTimer_Elapsed;
                InspectTimer.Interval = 30 * 1000;//30秒
                InspectTimer.Start();
            }
            catch (Exception ex)
            {
                Logger?.LogError(ex.Message, ex);
            }
        }

        private void ProduceDataUploaderTimer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            if (this.AppConfig.CurrentValue.ManualUpload)//离线测厚
            {
                // 尝试同步地获取信号量，不等待
                bool lockAcquired = uploadSemaphore.Wait(0);
                if (!lockAcquired)
                {
                    Logger?.LogWarning("同步任务已在运行，跳过此次调用。");
                    return;
                }
                try
                {
                    //Monitor here
                    ProduceDataUploaderCancelToken?.Cancel();
                    ProduceDataUploaderCancelToken = new CancellationTokenSource();
                    var task1 = UploadTodayScanData();
                    /*
                    sfliu 2025年3月5号 注释，原因：客户反映说昨天的数据，为什么今天才传，所以把昨天的数据同步移除掉了
                    ，仅传送当前的数据，当前的数据滚动传送的话，并不存在昨天的数据之说。
                    */
                    var task2 = UploadYesterdayScanData();
                    Task.WaitAll(task1, task2);
                    
                    Task.WaitAll(task1);
                    uploadSemaphore.Release();
                }
                catch (Exception)
                {
                    uploadSemaphore.Release();
                }

            }
            else
            {

            }
        }
        private static readonly SemaphoreSlim uploadSemaphore = new SemaphoreSlim(1, 1);
        private static readonly SemaphoreSlim syncAppDataSemaphore = new SemaphoreSlim(1, 1);
        private static readonly SemaphoreSlim localSyncSemaphore = new SemaphoreSlim(1, 1);
        private static readonly SemaphoreSlim inspectDataSemaphore = new SemaphoreSlim(1, 1);
        int ret1 = 0;
        int ret2 = 0;
        int ret3 = 0;
        int ret4 = 0;
        int ret5 = 0;
        int ret6 = 0;

        private Task UploadYesterdayScanData()
        {

            //此处用于遍历四处数据类型用于上传 
            //定期解析数据到报表库
            return Task.Run(async () =>
            {
                ILocalDataService service = null!;
                try
                {
                    service = provider.GetService<ILocalDataService>();
                    var ret = 0;
                    do
                    {
                        try
                        {
                            //上传前一日胎面数据
                            ret = service.SyncSemiSteelTreadScanReport_YST_ToRemote();
                            ret1 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(1000);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);

                    do
                    {
                        try
                        {
                            //上传前一日胎侧数据
                            ret = service.SyncSemiSteelSideInspectionReport_YST_ToRemote();
                            ret2 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(1000);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);

                    do
                    {
                        try
                        {
                            //上传前一日胎侧数据
                            ret = service.SyncSemiSteelTriangleRubberReport_YST_ToRemote();
                            ret2 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(1000);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);

                    do
                    {
                        try
                        {
                            //上传前一日班前标准块数据
                            ret = service.SyncPrecheckTreadScanReport_YST_ToRemote();
                            ret6 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(100);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);
                }
                catch (Exception)
                {
                    GC.SuppressFinalize(service);
                    this.Logger?.LogError("");
                }
                finally
                {

                }
            }, ProduceDataUploaderCancelToken.Token);
        }
        /// <summary>
        /// 遍历四组类型数据，以上传
        /// 定期解析数据到报表库
        /// </summary>
        /// <returns></returns>
        private Task UploadTodayScanData()
        {
            return Task.Run(async () =>
            {
                ILocalDataService service = null!;
                try
                {
                    service = provider.GetService<ILocalDataService>();
                    var ret = 0;
                    do
                    {
                        try
                        {
                            //上传当日胎面数据
                            ret = service.SyncSemiSteelTreadScanReportToRemote<CurrentReportContext>();
                            ret3 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(100);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);
                    do
                    {
                        try
                        {
                            //上传当日胎侧数据
                            ret = service.SyncSemiSteelSideInspectionReportToRemote<CurrentReportContext>();
                            ret4 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(100);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);
                    do
                    {
                        try
                        {
                            //上传当日三角胶数据
                            ret = service.SyncSemiSteelTriangleRubberReportToRemote<CurrentReportContext>();
                            ret5 += ret;
                        }
                        catch (Exception)
                        {
                            break;
                        }
                        await Task.Delay(100);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);
                    do
                    {
                        try
                        {
                            //上传当日班前标准块数据
                            
                            ret = service.SyncPreCheckReportToRemote<CurrentReportContext>();
                            ret6 += ret;
                        }
                        catch (Exception ex)
                        {
                            Logger?.LogError(ex.Message, ex);
                            break;
                        }
                        await Task.Delay(100);
                    } while (!ProduceDataUploaderCancelToken.IsCancellationRequested && ret > 0);
                }
                catch (Exception ex)
                {
                    GC.SuppressFinalize(service);
                    Logger?.LogError(ex.Message, ex);
                }
                finally
                {

                }
            }, ProduceDataUploaderCancelToken.Token);
        }

        /// <summary>
        /// 用于检查创建次日的数据库
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void DbCheckerTimer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            try
            {
                //定期检查创建次日数据库
                using (var scope = provider.CreateScope())
                {
                    try
                    {
                        if (LastCreateNextReportDbDate is null || LastCreateNextReportDbDate < DateTime.Now.Date)
                        {
                            var context = new CustomReportContext(this.AppConfig, DateOnly.FromDateTime(DateTime.Now.AddDays(1)));//此处应当使用实例化方式获取DBContext

                            if (CreateReportDbDetails(context))
                            {
                                LastCreateNextReportDbDate = DateTime.Now.Date;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger?.LogError("检测到次日历史库缓存数据库无法连接", ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger?.LogError(ex.Message, ex);
            }

        }

        /// <summary>
        /// 创建报表数据库明细
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <returns></returns>
        private bool CreateReportDbDetails<T>(T context) where T : ReportContext
        {
            var createDbFlag = false;
            var isDeleted = false;
            //var localHis = new CustomReportContext(this.AppConfig, DateOnly.FromDateTime(DateTime.Now)); 
            //数据库文件是否存在
            var fileDbFileExists = context.GetDbFileCreated();
            if (fileDbFileExists)
                isDeleted = context.Database.EnsureDeleted();

            if (!fileDbFileExists || isDeleted)
            {
                createDbFlag = context.Database.EnsureCreated();
            }
            return createDbFlag;
        }

        CancellationTokenSource HisDataLocaSyncToMesCancelToken { get; set; }
        public System.Timers.Timer DbCheckerTimer { get; private set; }
        public DateTime? LastCreateNextReportDbDate { get; private set; }
        public System.Timers.Timer DataDecoupTimer { get; private set; }
        public CancellationTokenSource ProduceDataUploaderCancelToken { get; private set; }
        public CancellationTokenSource DataDecouperCancelToken { get; private set; }
        public System.Timers.Timer InspectTimer { get; private set; }

        /// <summary>
        /// 定期下载中间表数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void InspectTimer_Elapsed(object? sender, ElapsedEventArgs e)
        {
            DownloadInspectData();
        }
        private CancellationTokenSource DownloadInspectDataCancelToken;

        /// <summary>
        /// 下载中间表数据
        /// </summary>
        internal void DownloadInspectData()
        {// 尝试同步地获取信号量，不等待
            bool lockAcquired = inspectDataSemaphore.Wait(0);
            if (!lockAcquired)
            {
                Logger?.LogWarning("下载中间表任务已在运行，跳过此次调用。");
                return;
            }
            DownloadInspectDataCancelToken?.Cancel();
            DownloadInspectDataCancelToken = new CancellationTokenSource();
            Task.Run(() =>
            {
                try
                {
                    int ret = 0;
                    const int pageSize = 50;
                    do
                    {
                        //远程中间表数据
                        var localDbService = provider.GetService<ILocalDataService>();

                        var service = provider.GetService<IYB_LOT_INSPECTService>();
                        var localService = provider.GetService<IYB_LOT_INSPECT_LocalService>();
                        var hyperService = provider.GetService<IHyperDbService>();
                        string[] machineNoList = localDbService.GetAll<EquipmentMapping>().Select(T => T.EqpNo).ToArray();
                        //To do,通过SERIAL_NUMBER顺序差找中间表数据,按照50条数据作为分页查找方式,防止条目过大无法更新状态
                        var inspectList = service.GetSnPage(0, pageSize, T => T.RECEIVE_FLAG == __REMOTE_SYNC_STATE_PENDING && machineNoList.Contains(T.EQP), T => T.SERIAL_NUMBER);
                        ret = hyperService.SyncInspectData(inspectList);
                        if (ret > 0)//成功更新以及插入
                        {
                            //do somethings
                            Debug.WriteLine($"InspectTimer_Elapsed:定期下载中间表数据成功{ret}条");
                        }
                    } while (!DownloadInspectDataCancelToken.Token.IsCancellationRequested && ret == pageSize);
                    inspectDataSemaphore.Release();
                }
                catch (Exception ex)
                {
                    Logger?.LogError("定期下载中间表数据", ex);
                    Debug.WriteLine($"InspectTimer_Elapsed:定期下载中间表数据失败:{ex.Message}");
                    inspectDataSemaphore.Release();
                }
            }, DownloadInspectDataCancelToken.Token);
        }

        /// <summary>
        /// 定期同步数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SyncSpecInfoTimer_Elapsed(object sender, ElapsedEventArgs e)
        {

        }

        /// <summary>
        /// 定期删除数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DataCleanerTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                var reportConStringTemplate = this.AppConfig.CurrentValue.LocalReportConnectionStringTemplate;
                int cleanerDbDaysInterval = this.AppConfig.CurrentValue.DataCleanerDaysInterval;

                // 使用正则表达式匹配 Data Source 的值
                var match = Regex.Match(reportConStringTemplate, @"Data Source=([^;]+)(;|$)");
                if (match.Success)
                {
                    var conStr = match.Value.TrimStart("Data Source=".ToArray());
                    var dictoryPath =Path.GetDirectoryName(Path.GetFullPath(conStr));
                    if (Directory.Exists(dictoryPath))
                    {
                        //var dbFiles = Directory.GetFiles(dictoryPath, "*.mdb");
                        var dbFiles = Directory.GetFiles(dictoryPath, "*.sqlite3");
                        foreach (var dbFile in dbFiles)
                        {
                            var dateStr = System.IO.Path.GetFileNameWithoutExtension(dbFile);
                            DateTime date = DateTime.ParseExact(dateStr, "yyyy-MM-dd", null);
                            if (Math.Abs((date - DateTime.Now).TotalDays) > cleanerDbDaysInterval)//保留5天缓存数据
                            {
                                try
                                {
                                    File.Delete(dbFile);
                                }
                                catch (Exception ex)
                                {
                                    Logger?.LogError($"清理历史报表数据失败{ex.Message}", ex);
                                }
                            }
                        }
                    }
                }


                var localDbService = provider.GetService<ILocalDataService>();
                //删除大于30天中间表条码同步记录
                var ret = localDbService.RemoveTimeovered(cleanerDbDaysInterval);
                Debug.WriteLine($"DataCleanerTimer_Elapsed:定期删除数据:{ret}条");
                Logger?.LogInformation($"DataCleanerTimer_Elapsed:定期删除数据:{ret}条");

            }
            catch (Exception ex)
            {
                Logger?.LogError("删除大于30天同步记录失败", ex);
            }
        }
    }
}
